package com.gyt.data.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.gyt.data.dao.risk.FunctionMapper;
import com.gyt.data.service.FunctionService;
import com.gyt.framework.common.utils.AesUtil;
import com.gyt.framework.common.utils.DocUtil;
import com.gyt.framework.common.utils.RegUtil;
import com.gyt.framework.component.RedisComponent;
import com.gyt.framework.domain.function.req.FunctionTypeReq;
import com.gyt.framework.domain.function.result.FunctionInfoResult;
import com.gyt.framework.domain.function.result.FunctionRelatedSceneResult;
import com.gyt.framework.domain.function.risk.FunctionLibraryInfo;
import com.gyt.framework.domain.function.risk.FunctionLibraryParam;
import com.gyt.framework.exception.BaseException;
import com.lowagie.text.DocumentException;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

/**
 * @Author created by v_yantgao
 * @Date 2021/1/7 16:45
 */
@Service
public class FunctionServiceImpl implements FunctionService {

    private final static Logger logger = LoggerFactory.getLogger(FunctionServiceImpl.class);

    @Autowired
    private FunctionMapper functionMapper;

    private static Map<String,Object> cacheMap = Maps.newConcurrentMap();

    private static final String cacheKey = "cache_fun";

    @Autowired
    private RedisComponent redisComponent;

    private static final String tempFileName = "interTemplate.ftl";
    private static final String targetFilePdfName = "outTemplate.pdf";
    private static final String targetFileDocName = "outTemplate.doc";

    public ResponseEntity<byte[]> exportExcel(){
        ResponseEntity responseEntity = null;
        try {
            List<Map<String, Object>> list = Lists.newArrayList();
            Map<String, Object> map = Maps.newHashMap();
            map.put("name", "lily");
            map.put("age", 15);
            list.add(map);
            Workbook workbook = new HSSFWorkbook();
            Sheet sheet = workbook.createSheet("用户信息");
            Row row = sheet.createRow(0);//表头
            workbook.createCellStyle().setAlignment(HSSFCellStyle.ALIGN_CENTER);//居中
            Cell cell = row.createCell(0);
            cell.setCellValue("姓名");
            cell = row.createCell(1);
            cell.setCellValue("年龄");
            for (int i = 0; i < list.size(); i++) {
                Map<String, Object> resultMap = list.get(i);
                row = sheet.createRow(i + 1);
                row.createCell(0).setCellValue(resultMap.get("name").toString());
                row.createCell(1).setCellValue(resultMap.get("age").toString());
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(baos, "UTF-8");
            BufferedWriter writer = new BufferedWriter(outputStreamWriter);
            responseEntity = new ResponseEntity(baos.toByteArray(), null, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return responseEntity;
    }
    @Override
    public List<String> getExcelInfo(){
        Resource resource = new ClassPathResource("/config/template/20200505082448.xlsx");
        List<String> list = Lists.newArrayList();
        try {
            InputStream inputStream = resource.getInputStream();
            Workbook sheets = WorkbookFactory.create(inputStream);
            if (sheets == null)return list;
            Sheet sheet = sheets.getSheetAt(0);
            if (sheet == null)return list;
            for (int i = 0; i < 10; i++) {//sheet.getLastRowNum()
                if (i == 0)continue;
                Row row = sheet.getRow(i);
                Cell zero = row.getCell(0);
                String zeroValue = DocUtil.getCellValue(zero);
                list.add(zeroValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    @Override
    public List<String> importByExcel(InputStream inputStream) {
        List<String> list = Lists.newArrayList();
        try {
            Workbook workbook = WorkbookFactory.create(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
            for (int i = 1; i < 10; i++) {
                Row row = sheet.getRow(i);
                Cell cell = row.getCell(0);
                String cellValue = DocUtil.getCellValue(cell);
                list.add(cellValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    @Override
    public void downloadPdf(HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> dataMap = new HashMap<>();

        List<Map<String, String>> inParams = new ArrayList<>();
        Map<String, String> inParamMap = new HashMap<>();
        inParamMap.put("inParamEnName","sys");
        inParamMap.put("inParamCnName","系统");
        inParamMap.put("inParamSymbol","");
        inParams.add(inParamMap);

        List<Map<String, String>> outParams = new ArrayList<>();
        Map<String, String> outParamMap = new HashMap<>();
        outParamMap.put("outParamEnName","out");
        outParamMap.put("outParamType","string");
        outParamMap.put("outParamCnName","输出");
        outParamMap.put("outParamState","Y");
        outParams.add(outParamMap);

        List<Map<String, String>> outParamsResult = new ArrayList<>();
        Map<String, String> outParamsResultMap = new HashMap<>();
        outParamsResultMap.put("outParamEnName", "output");
        outParamsResultMap.put("outParamCnName", "输出");
        outParamsResultMap.put("outParamSymbol", "");
        outParamsResult.add(outParamsResultMap);

        dataMap.put("fappid", AesUtil.makeAppId());
        dataMap.put("fapptoken", AesUtil.makeAppToken());
        dataMap.put("sceneId", 110);
        dataMap.put("inParams",inParams);
        dataMap.put("outParams",outParams);
        dataMap.put("outParamsResult",outParamsResult);

        File file = null;
        FileInputStream inputStream = null;
        ServletOutputStream outputStream = null;
        try {
//            file = DocUtil.getPdfFile(dataMap, tempFileName, targetFilePdfName);
            file = DocUtil.getDocFile(dataMap, tempFileName, targetFileDocName);
            inputStream = new FileInputStream(file);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/msword;charset=UTF-8");
//            response.setContentType("application/pdf;charset=UTF-8");
            response.addHeader("Content-Disposition", "attachment;filename=" + targetFileDocName);
            outputStream = response.getOutputStream();
            byte[] buffer = new byte[inputStream.available() + 1000];
            int lengthRead;
            while ((lengthRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, lengthRead);
            }
            outputStream.flush();
        } catch (IOException e) {
            logger.error("parse stream fail", e);
        } finally {
            try {
                if (inputStream != null)
                    inputStream.close();
                if (outputStream != null)
                    outputStream.close();
            } catch (IOException e) {
                logger.error("closed stream exception", e);
            }
            //删除临时文件
            if (file != null)
                file.deleteOnExit();
        }
    }

    public List<FunctionRelatedSceneResult> getRelatedFunsBySceneId(String keyWord, Integer sceneId) {
        //Assert.notNull(keyWord, "参数为空");
        Map<String, Object> map = Maps.newHashMap();
        map.put("keyWord", keyWord);
        map.put("sceneId", sceneId);
        map.put("featureType", 6);
        long start = System.currentTimeMillis();
        List<FunctionRelatedSceneResult> relatedFuns = functionMapper.getRelatedFunsBySceneId(map);
        if (CollectionUtils.isNotEmpty(relatedFuns)){
            for (FunctionRelatedSceneResult relatedFun : relatedFuns) {
                List<FunctionInfoResult> funs = relatedFun.getFunctionResultList();
                for (FunctionInfoResult fun : funs) {
                    Integer funFid = fun.getFid();
                    List<FunctionLibraryParam> outParams = functionMapper.queryFunctionOutParamList(funFid, 2);
                    if (CollectionUtils.isNotEmpty(outParams)){
                        fun.setCheckOutParam(true);
                        fun.setFdataType(outParams.get(0).getFdataType());
                    }
                }
            }
        }
        logger.info("cost time:{} ms",(System.currentTimeMillis()-start) );
        return relatedFuns;
    }

    @Override
    public List<FunctionLibraryInfo> getFunTypeInfoList(){
        String groupId = "fun_type";
        String key = "fun_type_all";
        String cacheResult = redisComponent.getRedisCache(groupId, key);
        if (StringUtils.isNotBlank(cacheResult)) {
            return JSON.parseArray(cacheResult, FunctionLibraryInfo.class);
        }else {
            List<FunctionLibraryInfo> libraryInfos = functionMapper.getFunctionLibraryAllInfo();
            redisComponent.putRedisCache(groupId, key, JSON.toJSONString(libraryInfos));
            return libraryInfos;
        }
    }
    @Override
    public FunctionLibraryInfo getFunctionLibraryInfoById(Integer fid){
        //redis的简单应用
        String key = cacheKey + fid;
        if (cacheMap.get(key) != null) {
            return (FunctionLibraryInfo) cacheMap.get(key);
        }else {
            FunctionLibraryInfo libraryInfo = functionMapper.getFunctionLibraryInfoById(fid);
            cacheMap.put(key, libraryInfo);
            return functionMapper.getFunctionLibraryInfoById(fid);
        }
    }

    @Override
    public void updateFunctionTypeInfo(FunctionTypeReq reqParam, String userName) {
        if (reqParam == null){
            throw new BaseException("500", "参数为空或错误！");
        }
        Date date = new Date();
        FunctionLibraryInfo funTypeParam = new FunctionLibraryInfo();
        if (!RegUtil.checkVarUpperEn(reqParam.getFfunctionTypeEnName())) {
            throw new BaseException("500", "函数类型英文名为纯英文且首字母大写！");
        }
        funTypeParam.setFfunctionTypeEnName(reqParam.getFfunctionTypeEnName());
        if (!RegUtil.checkVarCn(reqParam.getFfunctionTypeCnName())) {
            throw new BaseException("500", "函数类型中文名必须是纯中文！");
        }
        funTypeParam.setFfunctionTypeCnName(reqParam.getFfunctionTypeCnName());
        funTypeParam.setFmodifyTime(date);
        funTypeParam.setFupdateUser(userName);
        if (reqParam.getFid() != null){
            //更新函数类型信息
            funTypeParam.setFid(reqParam.getFid());
            functionMapper.updateFunctionTypeInfo(funTypeParam);
        }else {
            //新增函数类型信息
            funTypeParam.setFcreateUser(userName);
            funTypeParam.setFcreateTime(date);
            funTypeParam.setFstate(NumberUtils.SHORT_ONE);
            functionMapper.addFunctionTypeInfo(funTypeParam);
        }
    }
}
